package eu.robico.simulator.simulatorinterface.utils;

import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;

import eu.robico.simulator.simulatorinterface.actionpanel.Line;
import eu.robico.simulator.simulatorinterface.actionpanel.Position;

public class Toolkit 
{
	private Toolkit() {}
	
	public static double getDistance(Position firstPosition, Position otherPosition)
	{
		return getDistance(firstPosition.x, firstPosition.y, otherPosition.x, otherPosition.y);
	}
	
	public static double getDistance(double x, double y, Position position)
	{
		return getDistance(x, y, position.x, position.y);
	}
	
	public static double getDistance(double x1, double y1, double x2, double y2)
	{
		double xDiff = x1 - x2;
		double yDiff = y1 - y2;
		return Math.sqrt(Math.pow(xDiff, 2) + Math.pow(yDiff, 2));
	}
	
	public static Boundary moveBoundaryBy(Boundary bounds, double xDiff, double yDiff)
	{
		Position[] resultRectangle = new Position[4];
		for (int i = 0; i < 4; i++)
			resultRectangle[i] = new Position(
					bounds.getPoints().get(i).x + xDiff,
					bounds.getPoints().get(i).y + yDiff
			);
		
		//Return the rectangle
		return new Boundary(resultRectangle);
	}
	
	public static Position getCenter(Position p1, Position p2)
	{
		return new Position((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
	}
	
	public static Position rotatePosition(Position position, double rotation)
	{
		return new Position(
				rotateX(position.getX(), position.getY(), rotation),
				rotateY(position.getX(), position.getY(), rotation)
		);
	}
	
	public static Position rotatePosition(Position position, Position center, double rotation)
	{
	    return new Position(
	    		center.getX() + rotateX(position.getX() - center.getX(), position.getY() - center.getY(), rotation),
	    		center.getY() + rotateY(position.getX() - center.getX(), position.getY() - center.getY(), rotation)
	    );
	}
	
	public static double rotateX(double x, double y, double angle)
	{
		return (x*Math.cos(Math.toRadians(angle)) - y*Math.sin(Math.toRadians(angle)));
	}
	
	public static double rotateY(double x, double y, double angle)
	{
		return (x*Math.sin(Math.toRadians(angle)) + y*Math.cos(Math.toRadians(angle)));
	}
	
	public static List<Line> boundaryToLines(Boundary bounds)
	{
		List<Line> lines = new ArrayList<>();
		for (int i = 0; i < 4; i ++)
		if (i == 3)
			lines.add(new Line(bounds.getPoints().get(i), bounds.getPoints().get(0)));
		else
			lines.add(new Line(bounds.getPoints().get(i), bounds.getPoints().get(i + 1)));
		return lines;
	}
	
	public static boolean intersect(
			Position startLine1, 
			Position endLine1,
			Position startLine2,
			Position endLine2)
	{
		double x1 = startLine1.getX();
		double x2 = endLine1.getX();
		double x3 = startLine2.getX();
		double x4 = endLine2.getX();
		double y1 = startLine1.getY();
		double y2 = endLine1.getY();
		double y3 = startLine2.getY();
		double y4 = endLine2.getY();
		
		return Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x4, y4);
	}
	
	public static void paintBounds(Graphics2D graphics, Boundary bounds)
	{
		int[] 	xPoints = new int[bounds.getPoints().size()], 
				yPoints = new int[bounds.getPoints().size()];
		for (int i = 0; i < bounds.getPoints().size(); i++)
		{
			xPoints[i] = (int) bounds.getPoints().get(i).xAsInt();
			yPoints[i] = (int) bounds.getPoints().get(i).yAsInt();
		}
		graphics.fillPolygon(xPoints, yPoints, bounds.getPoints().size());
	}
}
